﻿using System;
using System.IO;
using System.Xml.Linq;
using System.Threading;
using Aso.TradingTerminalSuite.Common.Elastic;
using System.Reflection;
using System.ComponentModel.Composition;
using Caliburn.Micro;

namespace Aso.TinyTester.Core.Configuration
{
	[Export(typeof(IUserConfigurationRepository))]
	[PartCreationPolicy(CreationPolicy.Shared)]
	public class UserConfigurationRepository : IUserConfigurationRepository
	{
		[ImportingConstructor]
		public UserConfigurationRepository(IEventAggregator eventAggregator)
		{
			var ass = Assembly.GetEntryAssembly();
			var name = ass.GetName();
			var company = ((AssemblyCompanyAttribute) Attribute.GetCustomAttribute(
				Assembly.GetExecutingAssembly(), typeof (AssemblyCompanyAttribute), false))
				.Company;
			FilePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),company+"\\"+name+"\\"+"Application.config");
			_eventAggregator = eventAggregator;
		}

		public UserConfigurationRepository(IEventAggregator eventAggregator,string filePath):this(eventAggregator)
		{
			FilePath = filePath;
		}

		private IEventAggregator _eventAggregator;

		public String FilePath { get; private set; }

		private UserConfiguration _configuration;
		private readonly ReaderWriterLockSlim _lock=new ReaderWriterLockSlim();

		[Export(typeof(UserConfiguration))]
		public UserConfiguration Configuration
		{
			get
			{
				_lock.EnterReadLock();
				try
				{
					return _configuration ?? (_configuration = RetrieveFromFile());
				}
				finally
				{
					_lock.ExitReadLock();
				}
			}
		}

		public void SaveConfiguration(UserConfiguration configuration)
		{
			_lock.EnterWriteLock();
			try
			{
				configuration.ToXElement().Save(FilePath);
				_configuration = null;
				_eventAggregator.Publish(configuration);
			}
			finally
			{
				_lock.EnterWriteLock();
			}
		}

		public object RestoreApplicationFromLayout()
		{
			var config =Configuration;
			return LayoutHelper.CreateFromLayout(config);
		}

		public void SaveApplicationLayout(object appStart)
		{
			var config = Configuration;
			config.Layout.AddElement(LayoutHelper.GetLayout(appStart));
			SaveConfiguration(config);
		}

		private UserConfiguration RetrieveFromFile()
		{
			if (!File.Exists(FilePath))
			{
				return  new UserConfiguration();
			}
			using (var stream=File.OpenRead(FilePath))
			{
				return XElement.Load(stream).To<UserConfiguration>();
			}
		}
	}
}
